import numpy as np


def _squared_distance(a, b):
    """计算欧氏距离"""
    a, b = np.asarray(a), np.asarray(b)
    if len(a) == 0 or len(b) == 0:
        return np.zeros((len(a), len(b)))
    a2, b2 = np.square(a).sum(axis=1), np.square(b).sum(axis=1)
    r2 = -2. * np.dot(a, b.T) + a2[:, None] + b2[None, :]
    r2 = np.clip(r2, 0., float(np.inf))
    return r2


def _cosine_distance(a, b, data_is_normalized=False):
    """计算余弦距离"""
    a, b = np.asarray(a), np.asarray(b)
    if not data_is_normalized:
        a = a / np.linalg.norm(a, axis=1, keepdims=True)
        b = b / np.linalg.norm(b, axis=1, keepdims=True)
    return 1. - np.dot(a, b.T)


def nn_euclidean_distance(x, y):
    """返回一个长度为 len(y) 的向量，向量中的每个元素代表y中的元素到x中样本的最小欧式距离"""
    distances = _squared_distance(x, y)
    return np.maximum(0.0, distances.min(axis=0))


def nn_cosine_distance(x, y):
    """返回一个长度为 len(y) 的向量，向量中的每个元素代表y中的元素到x中样本的最小余弦距离"""
    distances = _cosine_distance(x, y)
    return distances.min(axis=0)
